const H5ClientDef = {}

H5ClientDef.FF00000000000000 = parseInt("FF00000000000000", 16);
H5ClientDef.FF000000000000 = parseInt("FF000000000000", 16);
H5ClientDef.FF0000000000 = parseInt("FF0000000000", 16);
H5ClientDef.FF00000000 = parseInt("FF00000000", 16);
H5ClientDef.FF000000 = parseInt("FF000000", 16);
H5ClientDef.FF0000 = parseInt("FF0000", 16);
H5ClientDef.FF00 = parseInt("FF00", 16);
H5ClientDef.FF = parseInt("FF", 16);

H5ClientDef.Cmd_Head_Size = 24;
H5ClientDef.Media_Head_Size = 20;
H5ClientDef.Login_Size = 112;
H5ClientDef.OpenStream_Size = 36;
H5ClientDef.CloseStream_Size = 32;

H5ClientDef.Cmd_Channel = {
    CMD_CHN:0,
    MAIN_STREAM1:1,
    SUB_STREAM1:2,
    LISTION_AUDIO_STREAM1:3,
    SPEEK_AUDIO_STREAM1:4,
    PLAY_BACK_STREAM1:5,
    MAIN_STREAM2:6,
    SUB_STREAM2:7,
    LISTION_AUDIO_STREAM2:8, 
    SPEEK_AUDIO_STREAM2:9,
    PLAY_BACK_STREAM2:10,
    MAIN_STREAM3:11,
    SUB_STREAM3:12,
    LISTION_AUDIO_STREAM3:13, 
    SPEEK_AUDIO_STREAM3:14,
    PLAY_BACK_STREAM3:15
}

H5ClientDef.Cmd_Type = {
    IOCTRL_TYPE_UNKN    :0x00,
    IOCTRL_DEV_LOGIN_REQ:0x01,  //登录命令
    IOCTRL_DEV_LOGIN_RESP:0x02,  //登录返回
    IOCTRL_TYPE_LIVE_START_REQ:0x03,   //开启流媒体命令
    IOCTRL_TYPE_LIVE_START_RESP:0x04,   //开启流媒体返回
    IOCTRL_TYPE_LIVE_STOP_REQ:0x05,   //关闭流媒体命令
    IOCTRL_TYPE_LIVE_STOP_RESP:0x06,   //关闭流媒体返回
    IOCTRL_HOST_GET_EVERYDAY_EXISTED_RECORD_FLAG_REQ:0x07,//搜索月标识
    IOCTRL_HOST_GET_EVERYDAY_EXISTED_RECORD_FLAG_RESP:0x08,//搜索月标识返回
    IOTYPE_USER_IPCAM_LISTEVENT_REQ : 0x09,//搜索录像文件
    IOTYPE_USER_IPCAM_LISTEVENT_RESP : 0x0A,//搜索录像文件返回
    IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL 		: 0x0B,
    IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL_RESP 	: 0x0C  
}

// typedef enum{
//     FRAME_TYPE_H264_I   = 1,
//     FRAME_TYPE_H264_P   = 2,
//     FRAME_TYPE_H265_I   = 3,
//     FRAME_TYPE_H265_P   = 4,
//     FRAME_TYPE_G711A    = 5,
// }EMUM_FRAME_TYPE;
H5ClientDef.Frame_Type = {
    FRAME_TYPE_H264_I   :1,
    FRAME_TYPE_H264_P   :2,
    FRAME_TYPE_H265_I   :3,
    FRAME_TYPE_H265_P   :4,
    FRAME_TYPE_G711A    :5
}

/**
 * 
typedef struct{
uint16_t chn; //通道号
unsigned char subDev; //子设备
    unsigned char res;//保留
    uint32_t datasize;//命令数据长度(结构体后面数据长度)    
    uint32_t cmdtype;//命令ENUM_CMD_TYPE
    uint32_t seq;//序号,返回序号=发送序号
    char Reserved[8];                
} P2PKIT_CMD_HEAD;
 *
 */
H5ClientDef.build_cmd_head = function(cmdType, seq, data){
    var dataSize = 0;
    if(data){
        dataSize = data.length;
    }    
    var buf = new ArrayBuffer(H5ClientDef.Cmd_Head_Size + dataSize);
    var bufView = new Uint8Array(buf);
    for(var i = 0; i<bufView.length; i++){
        bufView[i] = 0;
    }

    //前4个字节不填充，置0即可。
    //填充dataSize
    bufView[4] = (dataSize & H5ClientDef.FF);
    bufView[5] = (dataSize >> 8) & H5ClientDef.FF;
    bufView[6] = (dataSize >> 16) & H5ClientDef.FF;
    bufView[7] = (dataSize >> 24) & H5ClientDef.FF;
    //填弃cmdType
    bufView[8] = (cmdType & H5ClientDef.FF);
    bufView[9] = (cmdType >> 8) & H5ClientDef.FF;
    bufView[10] = (cmdType >> 16) & H5ClientDef.FF;
    bufView[11] = (cmdType >> 24) & H5ClientDef.FF;    
    //填充seq
    bufView[12] = (seq & H5ClientDef.FF);
    bufView[13] = (seq >> 8) & H5ClientDef.FF;
    bufView[14] = (seq >> 16) & H5ClientDef.FF;
    bufView[15] = (seq >> 24) & H5ClientDef.FF;   
    
    if(dataSize > 0){
        for(var i = 0; i<dataSize;i++){
            bufView[24 + i] = data[i];
        }
    }
    
    return bufView;
}

// typedef struct
// {
//     uint16_t chn; //通道号
//     unsigned char res[2];//保留
//     uint32_t datasize;//结构体后面数据长度 
//     uint32_t frameType;//EMUM_FRAME_TYPE  
//     uint32_t seq;//序号
//     uint32_t AVFramePTS; 
// } P2PKIT_MEDIA_HEAD;
H5ClientDef.build_media_head = function(chn, frameType, seq, pts, data){
    var dataSize = 0;
    if(data){
        dataSize = data.length;
    }
    var buf = new ArrayBuffer(H5ClientDef.Media_Head_Size + dataSize);
    var bufView = new Uinit8Array(buf);
    for(var i = 0; i<bufView.length; i++){
        bufView[i] = 0;
    }

    bufView[0] = chn & H5ClientDef.FF;
    bufView[1] = (chn >> 8) & H5ClientDef.FF;

    //填充dataSize
    bufView[4] = (dataSize & H5ClientDef.FF);
    bufView[5] = (dataSize >> 8) & H5ClientDef.FF;
    bufView[6] = (dataSize >> 16) & H5ClientDef.FF;
    bufView[7] = (dataSize >> 24) & H5ClientDef.FF;
    //填弃frameType
    bufView[8] = (frameType & H5ClientDef.FF);
    bufView[9] = (frameType >> 8) & H5ClientDef.FF;
    bufView[10] = (frameType >> 16) & H5ClientDef.FF;
    bufView[11] = (frameType >> 24) & H5ClientDef.FF;    
    //填充seq
    bufView[12] = (seq & H5ClientDef.FF);
    bufView[13] = (seq >> 8) & H5ClientDef.FF;
    bufView[14] = (seq >> 16) & H5ClientDef.FF;
    bufView[15] = (seq >> 24) & H5ClientDef.FF;
    //填充pts
    bufView[16] = (pts & H5ClientDef.FF);
    bufView[17] = (pts >> 8) & H5ClientDef.FF;
    bufView[18] = (pts >> 16) & H5ClientDef.FF;
    bufView[19] = (pts >> 24) & H5ClientDef.FF;
    
    if(dataSize > 0){
        for(var i = 0; i<dataSize;i++){
            bufView[20 + i] = data[i];
        }
    }
    
    return bufView;
}

H5ClientDef.parse_head = function(bufView){
    //检查第一个short是否为0，如果为0，则是CMD_HEAD，否则是MEDIA_HEAD
    //console.log(bufView);
    var hdr = {};
    hdr.chn = ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF)
    if(hdr.chn == H5ClientDef.Cmd_Channel.CMD_CHN){
        //指令
        hdr.subDev = bufView[2];
        hdr.res = bufView[3];
        hdr.dataSize = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
        hdr.cmdType = ((bufView[11] << 24) & H5ClientDef.FF000000) | ((bufView[10] << 16) & H5ClientDef.FF0000) | ((bufView[9] << 8) & H5ClientDef.FF00) | (bufView[8] & H5ClientDef.FF);
        hdr.seq = ((bufView[15] << 24) & H5ClientDef.FF000000) | ((bufView[14] << 16) & H5ClientDef.FF0000) | ((bufView[13] << 8) & H5ClientDef.FF00) | (bufView[12] & H5ClientDef.FF);
        hdr.reserved = new Uint8Array(8);
        for(var i = 0; i < 8; i++){
            hdr.reserved[i] = bufView[i + 16];
        }
    }
    else{
        //媒体
        hdr.res = new Uint8Array(2);
        hdr.res[0] = bufView[2];
        hdr.res[1] = bufView[3];
        hdr.dataSize = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
        hdr.frameType = ((bufView[11] << 24) & H5ClientDef.FF000000) | ((bufView[10] << 16) & H5ClientDef.FF0000) | ((bufView[9] << 8) & H5ClientDef.FF00) | (bufView[8] & H5ClientDef.FF);
        hdr.seq = ((bufView[15] << 24) & H5ClientDef.FF000000) | ((bufView[14] << 16) & H5ClientDef.FF0000) | ((bufView[13] << 8) & H5ClientDef.FF00) | (bufView[12] & H5ClientDef.FF);        
        hdr.pts = ((bufView[19] << 24) & H5ClientDef.FF000000) | ((bufView[18] << 16) & H5ClientDef.FF0000) | ((bufView[17] << 8) & H5ClientDef.FF00) | (bufView[16] & H5ClientDef.FF);    
    }

    return hdr;
}

// typedef struct
// {
//     char pwd[64]; //设备密码      
//     uint32_t playBits1;//bit0 -bit31;播放对应通道；比如bit0 被设置，播放通道0  
//     uint32_t playBitsRes[7];//保留
//     char res[16]; //保留
// } SLOGINReq;
H5ClientDef.build_login = function(pwd){
    var buf = new ArrayBuffer(H5ClientDef.Login_Size);   
    var bufView = new Uint8Array(buf);

    for(var i = 0; i<bufView.length; i++){
        bufView[i] = 0;
    }

    for(var i = 0; i<pwd.length; i++){
        bufView[i] = pwd.charCodeAt(i);
    }
    return bufView;
}

// typedef struct
// {
//     int32_t state; //0 成功，其它见ENUM_ERR
//     uint32_t softVer; //设备版本号
//     uint32_t playBits1;//返回播放情况;bit0 -bit31;对应通道是否播放；比如bit0 被设置，播放通道0  
//     uint32_t playBitsRes[7];//保留    
//     uint16_t mainStreamW;//主码流宽
//     uint16_t mainStreamH;//主码流高
//     uint16_t subStreamW;//从码流宽
//     uint16_t subStreamH;//从码流高
//     uint32_t devType; //设备类型
//     uint32_t capacityBits1;//设备能力级bit位
//     uint32_t capacityBits2;//设备能力级bit位
//     uint32_t capacityBitsRes[2];//设备能力级bit位
// } SLOGINResp;
H5ClientDef.parse_login_res = function(bufView){
    console.log(bufView.length, bufView);
    var res = {};
    res.state = ((bufView[3] << 24) & H5ClientDef.FF000000) | ((bufView[2] << 16) & H5ClientDef.FF0000) | ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF);
    res.softVer = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
    res.playBits1 = ((bufView[11] << 24) & H5ClientDef.FF000000) | ((bufView[10] << 16) & H5ClientDef.FF0000) | ((bufView[9] << 8) & H5ClientDef.FF00) | (bufView[8] & H5ClientDef.FF);
    res.playBitsRes = [];
    for(var i = 0;i < 7; i++){
        //res.playBitsRes[i] = bufView[i+12];
        var res1 = ((bufView[15 + i * 4] << 24) & H5ClientDef.FF000000) | ((bufView[14 + i * 4] << 16) & H5ClientDef.FF0000) | ((bufView[13 + i * 4] << 8) & H5ClientDef.FF00) | (bufView[12 + i * 4] & H5ClientDef.FF);
        res.playBitsRes.push(res1);
    }
    res.mainStreamW = ((bufView[41] << 8) & H5ClientDef.FF00) | (bufView[40] & H5ClientDef.FF);
    res.mainStreamH = ((bufView[43] << 8) & H5ClientDef.FF00) | (bufView[42] & H5ClientDef.FF);
    res.subStreamW = ((bufView[45] << 8) & H5ClientDef.FF00) | (bufView[44] & H5ClientDef.FF);
    res.subStreamH = ((bufView[47] << 8) & H5ClientDef.FF00) | (bufView[46] & H5ClientDef.FF);
    res.devType = ((bufView[51] << 24) & H5ClientDef.FF000000) | ((bufView[50] << 16) & H5ClientDef.FF0000) | ((bufView[49] << 8) & H5ClientDef.FF00) | (bufView[48] & H5ClientDef.FF);
    res.capacityBits1 = ((bufView[55] << 24) & H5ClientDef.FF000000) | ((bufView[54] << 16) & H5ClientDef.FF0000) | ((bufView[53] << 8) & H5ClientDef.FF00) | (bufView[52] & H5ClientDef.FF);
    res.capacityBits2 = ((bufView[59] << 24) & H5ClientDef.FF000000) | ((bufView[58] << 16) & H5ClientDef.FF0000) | ((bufView[57] << 8) & H5ClientDef.FF00) | (bufView[56] & H5ClientDef.FF);
    res.capacityBitsRes = [];
    var res1 = ((bufView[63] << 24) & H5ClientDef.FF000000) | ((bufView[62] << 16) & H5ClientDef.FF0000) | ((bufView[61] << 8) & H5ClientDef.FF00) | (bufView[60] & H5ClientDef.FF);
    res.capacityBitsRes.push(res1);
    var res2 = ((bufView[67] << 24) & H5ClientDef.FF000000) | ((bufView[66] << 16) & H5ClientDef.FF0000) | ((bufView[65] << 8) & H5ClientDef.FF00) | (bufView[64] & H5ClientDef.FF);
    res.capacityBitsRes.push(res2);
    return res;
}

// typedef struct
// {
//     uint32_t playBits1;//bit0 -bit31;播放对应通道；比如bit0 被设置，播放通道0  
//     uint32_t playBitsRes[7];//保留
//     unsigned char sReserved[4];
// } SIoctrlStartLiveReq;

H5ClientDef.build_open_stream = function(){
    var buf = new ArrayBuffer(H5ClientDef.OpenStream_Size)
    var bufView = new Uint8Array(buf);
    for(var i = 0; i<bufView.length;i++){
        bufView[i] = 0;
    }
    return bufView;
}

// typedef struct
// {
//     int32_t state; //0 成功，其它见ENUM_ERR
//     uint32_t playBits1;//返回播放情况;bit0 -bit31;对应通道是否播放；比如bit0 被设置，播放通道0   
//     uint32_t playBitsRes[7];//保留
// } SIoctrlStartLiveResp;
H5ClientDef.parse_open_stream_res = function(bufView){
    var res = {};
    res.state = ((bufView[3] << 24) & H5ClientDef.FF000000) | ((bufView[2] << 16) & H5ClientDef.FF0000) | ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF);
    res.playBits1 = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
    return res;
}

// typedef struct
// {
//     uint32_t stopBits1;//bit0 -bit31;停止对应通道；比如bit1 被设置，停止通道1  
//     uint32_t stopBitsRes[7];//保留
// }SIoctrlStopLiveReq;
H5ClientDef.build_close_stream = function(){
    var buf = new ArrayBuffer(H5ClientDef.CloseStream_Size)
    var bufView = new Uint8Array(buf);
    for(var i = 0; i<bufView.length;i++){
        bufView[i] = 0;
    }
    return bufView;    
}

// typedef struct
// {
//     int32_t state; //0 成功，其它见ENUM_ERR
//     uint32_t stopBits1;//bit0 -bit31;对应通道停止成功；比如bit1 被设置，通道1停止  
//     uint32_t stopBitsRes[7];//保留
// }SIoctrlStopLiveResp;
H5ClientDef.parse_close_stream_res = function(bufView){
    var res = {};
    res.state = ((bufView[3] << 24) & H5ClientDef.FF000000) | ((bufView[2] << 16) & H5ClientDef.FF0000) | ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF);
    res.playBits1 = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
    return res;    
}

// typedef struct
// {  
//     int year;    //年
//     int month;  //月
// }SIoctrlGetEverydayExistedRecordFlagReq;
H5ClientDef.build_month = function(iYear, iMon){
    var buf = new ArrayBuffer(8)
    var bufView = new Uint8Array(buf);
    for(var i = 0; i<bufView.length;i++){
        bufView[i] = 0;
    }
    bufView[0] = iYear & H5ClientDef.FF;
    bufView[1] = (iYear >> 8) & H5ClientDef.FF;
    bufView[2] = (iYear >> 16) & H5ClientDef.FF;
    bufView[3] = (iYear >> 24) & H5ClientDef.FF;

    bufView[4] = (iMon) & H5ClientDef.FF;
    bufView[5] = (iMon >> 8) & H5ClientDef.FF;
    bufView[6] = (iMon >> 16) & H5ClientDef.FF;
    bufView[7] = (iMon >> 24) & H5ClientDef.FF;
    return bufView;   
}

// typedef struct
// {
//     unsigned int diskflag;  
//     char everyday[32];  //数组成员非0，表示对应天有录像
// }SIoctrlGetEverydayExistedRecordFlagResq;
H5ClientDef.parse_month_res = function(bufView){
    var res = {};
    res.diskFlag = ((bufView[3] << 24) & H5ClientDef.FF000000) | ((bufView[2] << 16) & H5ClientDef.FF0000) | ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF);
    res.everyDay = new Uint8Array(32);
    for(var i = 0; i<32; i++){
        res.everyDay[i] = bufView[i+4];
    }

    return res;
}

// typedef struct
// {
//     unsigned int stStartTime; 		// Begin time of Search event from ...
//     unsigned int stEndTime;	  		// End   time of Search to (search event)
//     unsigned char reserved[4];
// }SMsgAVIoctrlListEventReq;

H5ClientDef.build_find_rec = function(startTimeStamp, endTimeStamp){
    var buf = new ArrayBuffer(12)
    var bufView = new Uint8Array(buf);
    for(var i = 0; i<bufView.length;i++){
        bufView[i] = 0;
    }
    bufView[0] = startTimeStamp & H5ClientDef.FF;
    bufView[1] = (startTimeStamp >> 8) & H5ClientDef.FF;
    bufView[2] = (startTimeStamp >> 16) & H5ClientDef.FF;
    bufView[3] = (startTimeStamp >> 24) & H5ClientDef.FF;

    bufView[4] = endTimeStamp & H5ClientDef.FF;
    bufView[5] = (endTimeStamp >> 8) & H5ClientDef.FF;
    bufView[6] = (endTimeStamp >> 16) & H5ClientDef.FF;
    bufView[7] = (endTimeStamp >> 24) & H5ClientDef.FF;

    return bufView;
}

// typedef struct
// {
//     unsigned int stTime;//
//     short rec_time;  //录像时长
//     unsigned char event;
//     unsigned char res[1];
// }SAvEvent;
// typedef struct
// {
//     unsigned int  total;		// Total event amount in this search session
//     unsigned int  count;         //how much events in this package
//     unsigned char index;		// package index, 0,1,2...;
//     							// because avSendIOCtrl() send package up to 1024 bytes one time, you may want split search results to serveral package to send.
//     unsigned char endflag;		// end flag; endFlag = 1 means this package is the last one.
// 	   char rev[2];
//     SAvEvent stEvent[];		// 录像节点
// }SMsgAVIoctrlListEventResp;
H5ClientDef.parse_fund_rec_res = function(bufView){
    var res = {};
    res.total = ((bufView[3] << 24) & H5ClientDef.FF000000) | ((bufView[2] << 16) & H5ClientDef.FF0000) | ((bufView[1] << 8) & H5ClientDef.FF00) | (bufView[0] & H5ClientDef.FF);
    res.count = ((bufView[7] << 24) & H5ClientDef.FF000000) | ((bufView[6] << 16) & H5ClientDef.FF0000) | ((bufView[5] << 8) & H5ClientDef.FF00) | (bufView[4] & H5ClientDef.FF);
    res.index = ((bufView[9] << 8) & H5ClientDef.FF00) | (bufView[8] & H5ClientDef.FF);
    res.endFlag = ((bufView[11] << 8) & H5ClientDef.FF00) | (bufView[10] & H5ClientDef.FF);

    res.stEvent = new Array();
    for(var i = 0; i < res.count; i++){
        var stEvent = {};
        stEvent.stTime = ((bufView[15 + i * 8] << 24) & H5ClientDef.FF000000) | ((bufView[14 + i * 8] << 16) & H5ClientDef.FF0000) | ((bufView[13 + i * 8] << 8) & H5ClientDef.FF00) | (bufView[12 + i * 8] & H5ClientDef.FF);
        stEvent.recTimes = ((bufView[17 + i * 8] << 8) & H5ClientDef.FF00) | (bufView[16 + i * 8] | H5ClientDef.FF);
        stEvent.event = bufView[18 + i * 8];
        stEvent.res = bufView[19 + i * 8];
        res.stEvent.push(stEvent);
    }

    return res;
}

export default H5ClientDef
